package com.example.demo.demo3.server;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerWithGUI extends Application {
    // 端口号
    private static final int PORT = 8888;
    // 存储单号的集合
    private ObservableList<String> barcodeList = FXCollections.observableArrayList();
    // 存储重量的集合
    private ObservableList<Double> weightList = FXCollections.observableArrayList();
    // 存储体积的集合
    private ObservableList<Double> volumeList = FXCollections.observableArrayList();
    // 显示日志的文本域
    private TextArea logTextArea;
    // 显示单号列表
    private ListView<String> barcodeListView;
    // 显示重量列表
    private ListView<Double> weightListView;
    // 显示体积列表
    private ListView<Double> volumeListView;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        // 创建界面元素
        logTextArea = new TextArea();
        // 设置不可编辑
        logTextArea.setEditable(false);
        // 把集合中的数据存储到表中
        barcodeListView = new ListView<>(barcodeList);
        weightListView = new ListView<>(weightList);
        volumeListView = new ListView<>(volumeList);

        // 声明条码标签、重量标签、体积标签
        Label barcodeLabel = new Label("条形码列表");
        Label weightLabel = new Label("重量列表");
        Label volumeLabel = new Label("体积列表");

        // 垂直布局界面,垂直间距为20px
        VBox vbox = new VBox(20);
        // 把日志文本域、单号标签、单号列表视图、重量标签、重量列表视图、体积标签、体积列表视图放入垂直布局中
        vbox.getChildren().addAll(logTextArea, barcodeLabel, barcodeListView, weightLabel, weightListView, volumeLabel, volumeListView);

        // 创建场景并显示窗口
        Scene scene = new Scene(vbox, 400, 600);
        primaryStage.setTitle("服务器界面");
        primaryStage.setScene(scene);
        primaryStage.show();

        // 启动服务器线程
        new Thread(this::startServer).start();
    }

    // 创建服务端开始方法
    private void startServer() {
        try (ServerSocket serverSocket = new ServerSocket(PORT)) // 初始化服务端套接字，并把端口传入
        {
            logMessage("服务器已启动，监听端口: " + PORT); // 调用logMessage方法打印
            while (true) {
                try (Socket clientSocket = serverSocket.accept(); // 等待客户端连接
                     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); // 发送信息
                     BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) // 获取信息
                {

                    logMessage("客户端已连接: " + clientSocket.getInetAddress()); // 打印客户端连接哪个服务端的地址
                    // 声明第三方参数，用于读取客户端发送的信息
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                        logMessage("收到客户端消息: " + inputLine);
                        // 以','的方式分割数据
                        String[] parts = inputLine.split(",");
                        // 以':'的方式再次分割数据,然后获取下标为1的数据
                        String barcode = parts[0].split(":")[1];
                        // 第二段数据，以':'的方式分割数据，获取下标为1 的数据
                        double weight = Double.parseDouble(parts[1].split(":")[1]);
                        // 第三段数据，以':'的方式分割数据，获取下标为1 的数据
                        double volume = Double.parseDouble(parts[2].split(":")[1]);

                        // 存储不同类型的数据到集合中
                        Platform.runLater(() -> {
                            barcodeList.add(barcode);
                            weightList.add(weight);
                            volumeList.add(volume);
                        });

                        // 根据接收的数据类型生成响应信息
                        String response = "单号 " + barcode + "、重量 " + weight + "、体积 " + volume;
                        // 发送响应信息给客户端
                        out.println(response);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    logMessage("发生异常: " + e.getMessage());
                }
            }
        } catch (IOException e) {
            logMessage("无法启动服务器: " + e.getMessage());
        }
    }

    // 创建日志信息方法，并且有一个字符串类型的形参
    private void logMessage(String message) {
        // 调用JavaFX中的线程方法，内部调用多行文本的appendText方法打印信息，appendText 方法用于在 TextArea 的末尾追加指定的文本内容，指定内容为message字符串
        Platform.runLater(() -> logTextArea.appendText(message + "\n"));
    }
}